{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 程序的基本结构"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们前面说过，编程就像教孩子，更具体地说，就像给孩子讲故事。编故事和讲故事是有套路的，最基本的离不开“角色”和“情节”，角色要生动独特，情节要跌宕起伏一波三折，就比较吸引人，最后完成了一个主旨的表述。\n",
    "\n",
    "以计算机为目标对象写故事，就要用编程语言的语法规则，在语法规则的体系内写清楚角色和情节，写出来的故事就是源代码（*source code*），然后通过编程语言的编译器或解释器让计算机运行源代码，得到我们想要的结果。\n",
    "\n",
    "理解程序的结构，就是理解编程语言提供给我们的“表达方式”有哪些，我们可以怎么去讲我们的故事。好的编程语言有很强的表达能力，用适合自己的编程语言书写代码经常会产生愉悦感，就来源于编程语言的表达力。\n",
    "\n",
    "编程语言这个东西，在程序员的世界里就好像时尚品牌，有喜欢这个牌子也有喜欢那个牌子的，程序员之间的闲聊多半都会导向“哪个编程语言最好”的话题，当然一般是得不出结果的。我个人认为好的编程语言应该具备几个特征：\n",
    "* 强表达能力：能够用简练的语法完成对各种逻辑的表达；\n",
    "* 有助于抽象：能够帮助程序员更好地进行问题的抽象；\n",
    "* 易于理解和学习：语法自然和流畅，容易为人所理解；\n",
    "* 有独特性：至少在某个特定领域有独特的优势，而不是面面俱到但处处平淡。\n",
    "\n",
    "随着学习越来越深入，大家也会有自己的感受，到时候我们也可以来谈谈，什么是我们心目中最好的编程语言。\n",
    "\n",
    "对我们目前阶段来说，Python 是一种非常好的教学语言，基本上满足上面列出的特征，大家可以在学习过程中自行体会。下面我们就以 Python 为例来理解程序的一般结构，也就是程序的表达方式。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 程序的基本结构（一）：值与变量"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "如果源代码是我们写出来的故事，那么“值和变量”就是故事的角色，是源代码中的“主语”和“宾语”。\n",
    "\n",
    "在程序的世界里出现的角色无非是各种数据，最基本的数据包括：\n",
    "* 逻辑上的真和假，大名叫布尔值（*boolean*）；\n",
    "* 各种数字，包括整数和小数（在计算机里叫浮点数 *float*）；\n",
    "* 表示文本的字符和字符串（*string*）。\n",
    "\n",
    "除了这些最基本的数据，还有几类“高级”一点的：\n",
    "* 对象：是我们可以自由定义的数据类型，一个对象可以有各种各样的属性（*attribute*）和方法（*method*）；在这一部分的后面会专门介绍对象；\n",
    "* 数据容器：可以容纳数据的数据，比如一列数字；我们会在第四部分专门学习数据容器；\n",
    "* 函数：函数是完成特定工作的一段源代码，函数是程序本身的组成部分，但函数也是数据，我们会在第四部分专门学习函数。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "数据在程序里的存在有两种形式，一种是“值（*value*）”，一种是“变量（*variable*）”。下面是一些值的例子：\n",
    "\n",
    "```python\n",
    "42\n",
    "3.14\n",
    "'a'\n",
    "'abracadabra'\n",
    "True\n",
    "False\n",
    "```\n",
    "\n",
    "值是有类型的，Python 提供了一个函数叫做 `type()`，可以告诉我们某个值是什么类型，我们可以试一下："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "int"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(42)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "float"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(3.14)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "str"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type('abracadabra')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "bool"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "上面的运行结果告诉我们：\n",
    "* `42` 类型是 `int`，这是 *integer* 的简写，即**整数**；\n",
    "* `3.14` 类型是 `float`，即**浮点数**，我们可以理解为就是**小数**；\n",
    "* `'abracadabra'` 类型是 `str`，这是 *string* 的简写，即**字符串**；\n",
    "* `False` 类型是 `bool`，这是 *boolean* 的简写，即**布尔值**，布尔值在计算机中代表逻辑上的真和假，只有两个布尔值，`True` 和 `False`。\n",
    "\n",
    "一般来说，同样类型的数据之间是可以发生一些“运算”的，比如数字之间可以加减乘除，字符串之间可以串接起来，布尔值之间可以进行逻辑运算，而不同类型的数据之间就好像不同物种一样，没法交互。所以搞清楚数据的类型是很重要的事情。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "有了值，我们就可以做计算，但是写不出真正的程序，为什么呢？因为程序写出来是希望能被很多人反复使用的——这些人叫做**用户**（*user*）——这样才比较划算，每次使用，用户输入一些数据，程序进行处理，然后给出用户想要的结果，每次的输入可能是同一类型，但具体的值是多少在我们写程序时是不知道的，所以我们需要一种东西能够来代替值写在程序中，而在程序运行时这些东西才根据用户的输入变成实际的“值”，这些“东西”就是**变量**。\n",
    "\n",
    "变量使得我们可以编写一个程序来处理一类值，而不管具体值是多少。我们学习代数的时候用 *a + b = b + a* 就表达了“加法交换律”这样高度抽象的普适规律，而不管 *a* 和 *b* 到底是多少，程序里的变量也一样，让我们能够进行“数据的抽象”，这个概念很重要，后面我们还会不断深化它。\n",
    "\n",
    "所有编程语言都支持值和变量，也支持把特定的值赋予某个变量，这样的操作叫做“**赋值**（*assignment*）”，下面是一些例子："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = 12\n",
    "b = 30\n",
    "f = 3.14\n",
    "s = 'abracadabra'\n",
    "l = [1, 2, 3]\n",
    "t = True\n",
    "f = False"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "赋值之后变量就具有了相应的值，**同时也具有了该值对应的类型**，所以变量一经赋值就有了类型："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "int"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "str"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(s)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "bool"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(t)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "list"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(l)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "最后的这个 `l` 是新东西，叫做**列表**（*list*），是一种数据容器，我们以后会详细介绍。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "如果我们想消灭一个变量不再使用，可以用 `del` 命令："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "del b"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这之后变量 `b` 就变成没有赋值的状态了，既没有值也没有类型，实际上无法使用——在哪儿用都会报错，不信你可以试试。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Python 还支持“多重赋值”，就是一次给多个变量赋值，比如这样："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "a, b = 12, 30"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "之后 `a` 的值就是 `12`，而 `b` 的值就是 `30`。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "赋值语句的右边不仅可以是值，也可以是变量，当一个变量写在赋值语句右边时，可以把它看做是“值的名字”，Python 解释器会把它替换成它的值（这个过程叫“**求值**”），比如："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "g = f"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "先把 `f` 替换为它的值，也就是 `False`，上面的语句就变成了 `g = False`，这样变量 `g` 就得到 `False` 这个值，以及 `bool` 类型。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 小结"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 值和变量是程序的基本组成，是程序里操作的对象，就像故事中的主角配角；\n",
    "* 值具有类型，了解值的类型很重要；\n",
    "* 变量是值的抽象，可以帮助我们处理用户输入的任何值；\n",
    "* 赋值语句是值与变量、变量与变量之间的桥梁。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
